package SquarePackage;

import static org.junit.Assert.*;

import java.math.BigDecimal;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import Border.Door;
import Border.Wall;


public class NormalSquaretest {

	/**
	 * @throws java.lang.Exception
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	private Wall testWall;
	private Door testDoor;

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		testNormalSquare = new NormalSquare(200, new BigDecimal(20));
		mergeTestNormalSquare =  new NormalSquare(200, new BigDecimal(60));
		testWall = new Wall(testNormalSquare, Direction.NORTH);
		testDoor = new Door(testNormalSquare, Direction.EAST);

	}

	/**
	 * @throws java.lang.Exception
	 */
	@After
	public void tearDown() throws Exception {
	}

	public NormalSquare testNormalSquare;
	public NormalSquare mergeTestNormalSquare;


	@Test 
	public final void setTemperatureTest(){
		testNormalSquare.setTemperature(200);
		assertEquals(200, testNormalSquare.getTemp(),0);         
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setTemperatureTooHighTest(){
		testNormalSquare.setTemperature(5001);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setTemperatureNegativeTest(){
		testNormalSquare.setTemperature(-201);
	}
	@Test
	public final void setBorderLegalCaseTest(){
		testNormalSquare.setBorder(Direction.NORTH, testWall);
		assertEquals(true, testNormalSquare.hasBorder(Direction.NORTH));
		assertEquals(3, testNormalSquare.numberOfBorders());
	}
	@Test	(expected = IllegalArgumentException.class)
	public final void setBorderIllegalCaseTest(){
		testNormalSquare.setBorder(null, testWall);
		testNormalSquare.setBorder(Direction.NORTH, null);
		assertEquals(2, testNormalSquare.numberOfBorders());
	}
	@Test
	public final void setBordersLegalTestCase(){
		testNormalSquare.setBorder(Direction.NORTH,testWall);
		testNormalSquare.setBorder(Direction.EAST, testDoor);
		assertTrue(testNormalSquare.hasBorder(Direction.EAST));
		assertTrue(testNormalSquare.hasBorder(Direction.NORTH));
		assertFalse(testNormalSquare.hasBorder(Direction.CEILING));
		assertFalse(testNormalSquare.hasBorder(Direction.WEST));
		assertEquals(3, testNormalSquare.numberOfBorders());
	}

	@Test
	public final void setBordersMaximumTest(){
		setAllWalls();
		assertEquals(6, testNormalSquare.numberOfBorders());
	}
	public void setAllWalls(){
		
		for(Direction direction : Direction.values()){
			testNormalSquare.removeBorder(direction);
			testNormalSquare.setBorder(direction, new Wall(testNormalSquare,direction));
		}
	}
	@Test 
	public final void removeBorderLegalCaseTest(){
		testNormalSquare.setBorder(Direction.NORTH,testWall);
		testNormalSquare.removeBorder(Direction.NORTH);
		assertEquals(2, testNormalSquare.numberOfBorders());
		assertFalse( testNormalSquare.hasBorder(Direction.NORTH));
	}
	@Test
	public final void removeBordersLegalCaseTest(){
		setAllWalls();
		testNormalSquare.removeBorders(Direction.NORTH);
		testNormalSquare.removeBorder(Direction.CEILING);
		assertEquals(4, testNormalSquare.numberOfBorders());
		assertFalse(testNormalSquare.hasBorder(Direction.NORTH));
		assertTrue( testNormalSquare.hasBorder(Direction.SOUTH));
		assertFalse(testNormalSquare.hasBorder(Direction.CEILING));
		assertTrue(testNormalSquare.hasBorder(Direction.WEST));
		assertTrue(testNormalSquare.hasBorder(Direction.FLOOR));
		assertTrue(testNormalSquare.hasBorder(Direction.EAST));

	}
	@Test
	public final void mergeWithNewTemperatureTest(){
		testNormalSquare.setTemperature(50);
		testNormalSquare.setHumidity(new BigDecimal(20));
		testNormalSquare.setBorder(Direction.NORTH,testWall);
		mergeTestNormalSquare.setTemperature(100);
		mergeTestNormalSquare.setHumidity(new BigDecimal(60));
		mergeTestNormalSquare.setBorder(Direction.SOUTH,new Wall(mergeTestNormalSquare,Direction.SOUTH));
		testNormalSquare.mergeWith(Direction.NORTH, mergeTestNormalSquare);
		assertEquals(85, testNormalSquare.getTemp(),0);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setWeightConstantIllegalCaseTooBigTest(){
		NormalSquare.setWeightConstant(0.5);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setWeightConstantIllegalCaseTooSmallTest(){
		NormalSquare.setWeightConstant(0);
	}
	@Test 
	public final void setWeightConstantLegalCasetest(){
		NormalSquare.setWeightConstant(0.30);
		assertEquals(0.3,NormalSquare.getWeightConstant(),0.00000001);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void mergeWithIllegalCaseNullTest(){
		testNormalSquare.mergeWith(Direction.NORTH,null);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void mergeWithIllegalCaseDirectionTest(){
		testNormalSquare.setBorder(Direction.EAST,testDoor);
		testNormalSquare.mergeWith(Direction.EAST,mergeTestNormalSquare);
	}
	@Test (expected = AssertionError.class)
	public final void setHumidityIllegalTest(){
		testNormalSquare.setHumidity(new BigDecimal(-100));
		assertEquals(20,testNormalSquare.getHumidity().doubleValue(),0.0000001);
	}
	@Test
	public final void getTempInKelvinTest(){
		assertEquals(473.15, testNormalSquare.getTemp(TemperatureScale.KELVIN),0);
	}
	@Test
	public final void getTempFahrenheitTest(){
		assertEquals(392, testNormalSquare.getTemp(TemperatureScale.FAHRENHEIT),1);
	}
	@Test   (expected = IllegalArgumentException.class)
	public final void setTemperatureIllegalCaseTest(){
		testNormalSquare.setTemperature(500000);
	}
	@Test
	public final void isValidTemperatureTrueCaseTest(){
		assertTrue(testNormalSquare.isValidTemperature(new Temperature(3000)));
	}
	@Test
	public final void isValidTemperatureFalseCaseTooHighTest(){
		assertFalse(testNormalSquare.isValidTemperature(new Temperature(5001)));
	}
	@Test
	public final void isValidTemperatureFalseCaseTooLowTest(){
		assertFalse(testNormalSquare.isValidTemperature(new Temperature(-201)));
	}
	@Test
	public final void isValidHumidityLegalcaseTest(){
		assertTrue(testNormalSquare.isValidHumidity(new BigDecimal(50)));
	}
	@Test
	public final void isValidHumidityFalseTest(){
		assertFalse(testNormalSquare.isValidHumidity(new BigDecimal(150)));
	}

	@Test
	public final void isValidHumidityFalseTest2(){
		assertFalse(testNormalSquare.isValidHumidity(new BigDecimal(-100)));
	}    
	@Test
	public final void canHaveAsTemperatureDomainTrueCaseTest(){
		assertTrue(testNormalSquare.canHaveAsTemperatureDomain(new Temperature(-200), new Temperature(100)));
	}
	@Test
	public final void canHaveAsTemperatureDomainTrueCaseTest2(){
		assertTrue(testNormalSquare.canHaveAsTemperatureDomain(new Temperature(-200), new Temperature(-200)));
	}
	@Test
	public final void canHaveAsTemperatureDomainFalseCaseTest(){
		assertFalse(testNormalSquare.canHaveAsTemperatureDomain(new Temperature(200), new Temperature(-200)));
	}
	public final void setTemperatureDomainTrueCaseTest() {
		testNormalSquare.setTemperatureDomain(new Temperature(-150), new Temperature(50));
		assertEquals(-150, testNormalSquare.getMinimumTemp(TemperatureScale.CELSIUS), 0);
		assertEquals(50.0, testNormalSquare.getMaximumTemp(TemperatureScale.CELSIUS),0);
	}
	@Test
	public final void setTemperatureDomainTrueCaseTest2() {
		testNormalSquare.setTemperature(new Temperature(-200));
		testNormalSquare.setTemperatureDomain(new Temperature(-200), new Temperature(-200));
		assertEquals(-200, testNormalSquare.getMinimumTemp(TemperatureScale.CELSIUS), 0);
		assertEquals(-200, testNormalSquare.getMaximumTemp(TemperatureScale.CELSIUS),0);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setTemperatureDomainFalseCaseTest() {
		testNormalSquare.setTemperatureDomain(new Temperature(-100), new Temperature(-500));
	}
	@Test
	public final void coldDamageLimitCaseTest(){
		testNormalSquare.setTemperature(-14);
		assertEquals(0, testNormalSquare.coldDamage(), 0);
	}
	@Test
	public final void ColdDamageVeryColdTest(){
		testNormalSquare.setTemperature(-200);
		assertEquals(19, testNormalSquare.coldDamage(), 0);
	}
	@Test
	public final void ColdDamageNoDamageTest(){
		testNormalSquare.setTemperature(100);
		assertEquals(0, testNormalSquare.coldDamage(), 0);
	}
	@Test
	public final void HeatDamageLimitTest(){
		testNormalSquare.setTemperature(49);
		assertEquals(0, testNormalSquare.heatDamage(), 0);
	}
	@Test
	public final void HeatDamageNoDamageTest(){
		testNormalSquare.setTemperature(-150);
		assertEquals(0, testNormalSquare.heatDamage(), 0);
	}
	@Test
	public final void HeatDamageVeryHotTest(){
		testNormalSquare.setTemperature(200);
		assertEquals(11, testNormalSquare.heatDamage(), 0);
	}
	@Test
	public final void RustDamageLowHumidityTest(){
		testNormalSquare.setHumidity(new BigDecimal("0.15"));
		assertEquals(0, testNormalSquare.rustDamage(), 0);
	}
	@Test
	public final void RustDamageHighHumidityTest(){
		testNormalSquare.setHumidity(new BigDecimal(50));
		assertEquals(2, testNormalSquare.rustDamage(), 0);
	}
	@Test
	public final void RustDamageLimitTest(){
		testNormalSquare.setHumidity(new BigDecimal(36));
		assertEquals(0, testNormalSquare.rustDamage(), 0);
	}
	@Test   (expected = IllegalArgumentException.class)
	public final void setHeat_Damage_ValuesIllegalAmount1Test(){
		NormalSquare.setHeat_Damage_Values(200, -10);
	}
	@Test   (expected = IllegalArgumentException.class)
	public final void setHeat_Damage_ValuesIllegalAmount2Test(){
		NormalSquare.setHeat_Damage_Values(200, 6000);
	}
	@Test
	public final void setHeat_Damage_ValuesLegalCaseTest(){
		NormalSquare.setHeat_Damage_Values(100, 50);
		assertEquals(100, NormalSquare.getHEAT_DAMAGE_TEMPERATURE(), 0);
		assertEquals(50, NormalSquare.getHEAT_DAMAGE_RATE(), 0);
	}
	@Test
	public final void setHumidityVeryLowLegalCaseTest(){
		testNormalSquare.setHumidity(new BigDecimal(5));
		assertEquals(5, testNormalSquare.getHumidity().doubleValue(),0);
	}
	@Test
	public final void setHumidityLegalCaseTest1(){
		testNormalSquare.setHumidity(new BigDecimal("12.3446"));
		assertEquals(12.34, testNormalSquare.getHumidity().doubleValue(),0);
	}
	@Test
	public final void setHumidityLegalCaseTest2(){
		testNormalSquare.setHumidity(new BigDecimal("12.5678"));
		assertEquals(12.57, testNormalSquare.getHumidity().doubleValue(),0);
	}
	@Test
	public final void setHumidityLegalCaseTest3(){
		testNormalSquare.setHumidity(new BigDecimal("0.1"));
		assertEquals(0.10, testNormalSquare.getHumidity().doubleValue(),0);
	}
	@Test
	public final void setHumidityLegalCaseTest4(){
		testNormalSquare.setHumidity(BigDecimal.ZERO);
		assertEquals(0.00, testNormalSquare.getHumidity().doubleValue(),0);
	}
	@Test
	public final void setSlipperyFirstScenarioTrueTest(){
		testNormalSquare.setHumidity(new BigDecimal(100));
		assertTrue(testNormalSquare.isSlippery());
	}
	@Test
	public final void setSlipperySecondScenarioTrueTest(){
		testNormalSquare.setTemperature(-20);
		testNormalSquare.setHumidity(new BigDecimal(60));
		assertTrue(testNormalSquare.isSlippery());
	}
	@Test
	public final void setSlipperyThirdScenarioTrueTest(){
		testNormalSquare.setMadeOfSlipperyMaterial(true);
		assertTrue(testNormalSquare.isSlippery());
	}
	@Test
	public final void setSlipperyFalseTest(){
		testNormalSquare.setMadeOfSlipperyMaterial(false);
		testNormalSquare.setHumidity(BigDecimal.ZERO	);
		testNormalSquare.setTemperature(10);
		assertFalse(testNormalSquare.isSlippery());
	}
	public final void mergeWithSimpleTemperatureTest(){
		testNormalSquare.setHumidity(new BigDecimal(50));
		mergeTestNormalSquare.setHumidity(new BigDecimal(50));
		testNormalSquare.setTemperature(50);
		testNormalSquare.setBorder(Direction.NORTH,testWall);
		mergeTestNormalSquare.setTemperature(100);
		mergeTestNormalSquare.setBorder(Direction.NORTH,new Wall(testNormalSquare,Direction.NORTH));
		testNormalSquare.mergeWith(Direction.NORTH,mergeTestNormalSquare);
		assertEquals(75, testNormalSquare.getTemp(),0);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setIllegalWeightConstantTooHighTest(){
		NormalSquare.setWeightConstant(0.5);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void setIllegalWeightConstantSmallerTest(){
		NormalSquare.setWeightConstant(0);
	}
	@Test 
	public final void setlegalWeightConstantTest(){
		NormalSquare.setWeightConstant(0.3);
		assertEquals(0.3,NormalSquare.getWeightConstant(),0);
	}
	@Test (expected = IllegalArgumentException.class)
	public final void mergeWithIllegalCaseTest(){
		testNormalSquare.mergeWith(Direction.EAST,null);
	}
	@Test 
	public final void mergeWithlegalCase2Test(){
		testNormalSquare.setBorder(Direction.CEILING,new Wall(testNormalSquare,Direction.CEILING));
		testNormalSquare.mergeWith(Direction.CEILING,mergeTestNormalSquare);
	}
//	@Test (expected = AssertionError.class)
//	public final void roundOffFalseTest(){
//		assertEquals(30.43,testNormalSquare.roundOff(30.438294),0.01);
//	}
//	@Test
//	public final void roundOffTrueTest(){
//		assertEquals(30.44, testNormalSquare.roundOff(30.4382), 0.01);
//	}
}